home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 52
/
Amiga Format AFCD52 (Issue 136, May 2000).iso
/
-in_the_mag-
/
multitasking
/
feature
/
snoopdos
/
snoopdos_source
/
hotkey.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-03-02
|
12KB
|
483 lines
/*
* HOTKEY.C vi:ts=4
*
* Copyright (c) Eddy Carroll, September 1994.
*
* Controls the management of the commodities hotkey for SnoopDos,
* along with other related stuff (Workbench AppIcon/Tools Menu support).
*/
#include "system.h"
#include "snoopdos.h"
#include "snooptext.h"
#include "icon.h"
extern char CommodityTitle[]; /* From SNOOPDOS.C */
struct NewBroker MyBroker = {
NB_VERSION,
"SnoopDos",
CommodityTitle,
NULL, /* Description, filled in at run time */
NBU_UNIQUE | NBU_NOTIFY,
COF_SHOW_HIDE,
0, 0, 0
};
struct MsgPort *BrokerMP; /* Message port used for msgs from CX */
CxObj *Broker; /* CX handle for the broker we created */
CxObj *Filter; /* Filter to filter CX messages */
struct MsgPort *WorkbenchPort; /* Port for AppIcon/AppMenu messages */
struct DiskObject *ProgramIcon; /* Handle on our program's icon data */
struct AppMenuItem *MyAppMenu; /* Current AppMenuItem, if any */
struct AppIcon *MyAppIcon; /* Current AppMenuItem, if any */
struct DiskObject *AppIconObj; /* Current object for AppMenuItem */
struct DiskObject *DefIconObj; /* A temporary default icon we use */
/*
* InstallHotKey(char *hotkey)
*
* Initialises commodity support and sets things up so that the
* key sequence specified by "hotkey" will send a CTRL-F activation
* signal to SnoopDos. We can also get various messages from the
* commodities exchange to show/hide the interface etc -- these
* will be indicated using CommodityMask.
*
* To see whether a hotkey is currently available or not, simply
* check the HotKeyActive flag. (This is used for disabling window
* gadgets etc.)
*
* Returns true for success, false for failure.
*/
int InstallHotKey(char *hotkey)
{
CxObj *newobj;
HotKeyActive = 0; /* Assume commodity is not currently active */
if (CurSettings.Setup.HideMethod == HIDE_NONE || !CxBase) {
/*
* Don't install a commodity at all if we have no hide
* method.
*/
return (0);
}
if (!BrokerMP) {
BrokerMP = CreateMsgPort();
if (!BrokerMP)
return (0);
CommodityMask = (1L << BrokerMP->mp_SigBit);
}
if (Broker && MyBroker.nb_Pri != CommodityPriority) {
/*
* The commodity priority has changed, so
* remove the current broker to force a new
* one to be created at the correct priority.
*/
DeleteCxObjAll(Broker);
Broker = NULL;
Filter = NULL;
}
if (!Broker) {
/*
* Attempt to create a new broker
*/
MyBroker.nb_Descr = MSG(MSG_COMMODITY_DESC);
MyBroker.nb_Port = BrokerMP;
MyBroker.nb_Pri = CommodityPriority;
Broker = CxBroker(&MyBroker, NULL);
if (!Broker)
return (0);
ActivateCxObj(Broker, 1);
}
/*
* Okay, now we create a new filter object to handle the
* commodity string we were passed
*/
if (Filter)
DeleteCxObjAll(Filter);
Filter = CxFilter(hotkey);
if (!Filter) {
/*
* Couldn't create the filter (probably out of memory --
* specifying an illegal hotkey doesn't cause this to
* fail, but instead produces an accumulated error later).
*
* We still leave the broker itself installed, since it can
* be used to allow the CX to send us Enable/Disable/Show/
* Hide/Quit messages.
*/
return (0);
}
/*
* Now add our various translation bits and pieces to the filter
*/
newobj = CxSignal(SysBase->ThisTask, SIGBREAKB_CTRL_F);
if (!newobj)
goto filter_error;
AttachCxObj(Filter, newobj);
newobj = CxTranslate(NULL);
if (!newobj)
goto filter_error;
AttachCxObj(Filter, newobj);
if (CxObjError(Filter))
goto filter_error;
AttachCxObj(Broker, Filter);
HotKeyActive = 1; /* Everything went okay so show we're active */
return (1);
filter_error:
DeleteCxObjAll(Filter);
Filter = NULL;
return (NULL);
}
/*
* HandleHotKey()
*
* Handles any incoming messages on the commodities exchange port.
* Should be called whenever a CommodityMask signal is received.
*/
void HandleHotKeyMsgs(void)
{
CxMsg *msg;
if (!BrokerMP)
return;
while ((msg = (CxMsg *)GetMsg(BrokerMP)) != NULL) {
ULONG msgid = CxMsgID(msg);
ULONG msgtype = CxMsgType(msg);
ReplyMsg((void *)msg);
if (msgtype == CXM_COMMAND) {
switch (msgid) {
case CXCMD_DISABLE:
SetMonitorMode(MONITOR_DISABLED);
break;
case CXCMD_ENABLE:
if (Disabled) /* Don't want to enable if Paused */
SetMonitorMode(MONITOR_NORMAL);
break;
case CXCMD_KILL:
QuitFlag = 1;
break;
case CXCMD_APPEAR:
case CXCMD_UNIQUE:
ShowSnoopDos();
break;
case CXCMD_DISAPPEAR:
HideSnoopDos();
break;
}
}
}
}
/*
* CleanupHotKey()
*
* Frees any resources used by the commodities module
*/
void CleanupHotKey(void)
{
if (Broker) {
DeleteCxObjAll(Broker);
Broker = NULL;
Filter = NULL;
}
if (BrokerMP) {
struct Message *msg;
while ((msg = GetMsg(BrokerMP)) != NULL)
ReplyMsg(msg);
DeleteMsgPort(BrokerMP);
BrokerMP = NULL;
CommodityMask = 0;
}
HotKeyActive = 0;
}
/*
* GetCommandName()
*
* Returns a pointer to a static string containing the name of
* this program. The pointer remains valid until the next call
* to this function.
*/
char *GetCommandName(void)
{
static char name[200];
struct Process *pr = (struct Process *)SysBase->ThisTask;
struct CommandLineInterface *cli = BTOC(pr->pr_CLI);
char *cmdname = (char *)BTOC(cli->cli_CommandName);
if (WBenchMsg)
return (WBenchMsg->sm_ArgList->wa_Name);
memcpy(name, cmdname+1, *cmdname);
name[*cmdname] = '\0';
return (name);
}
/*
* GetProgramIcon()
*
* Returns a pointer to an icon structure containing a program
* icon for SnoopDos, as follows:
*
* If SnoopDos was run from Workbench, we have a lock on it
* If SnoopDos was run from CLI, we look in the directory
* the program was run from. If we can't find it there, then
* we give up and use the default SnoopDos icon image.
*
* Regardless, you should call CleanupIcons() before exiting,
* to free up any loose icon images that may have been allocated.
*
* Warning: icon.library must be open when you call this function.
*/
struct DiskObject *GetProgramIcon(void)
{
if (ProgramIcon)
return (ProgramIcon);
if (WBenchMsg) {
/*
* Running from Workbench, so try and get the program icon
* indicated in the lock
*/
struct WBArg *wbarg = WBenchMsg->sm_ArgList;
BPTR lk;
lk = CurrentDir(wbarg->wa_Lock);
ProgramIcon = GetDiskObject(wbarg->wa_Name);
CurrentDir(lk);
} else {
/*
* Running from CLI so try and get icon associated with executable
*/
struct Process *pr = (struct Process *)SysBase->ThisTask;
BPTR lk;
if (pr->pr_HomeDir)
lk = CurrentDir(pr->pr_HomeDir);
ProgramIcon = GetDiskObject(GetCommandName());
if (pr->pr_HomeDir)
CurrentDir(lk);
}
if (ProgramIcon)
return (ProgramIcon);
/*
* Okay, unfortunately we couldn't locate the program icon, so
* instead, let's just fall back to the default icon.
*/
DefSnoopDosIcon.do_StackSize = MINSTACKSIZE; /* Fix this up here */
return (&DefSnoopDosIcon);
}
/*
* CleanupIcons()
*
* Frees any icon-related resources that were allocated
*/
void CleanupIcons(void)
{
RemoveProgramFromWorkbench();
if (ProgramIcon) {
FreeDiskObject(ProgramIcon);
ProgramIcon = NULL;
}
if (DefIconObj) {
FreeDiskObject(DefIconObj);
DefIconObj = NULL;
AppIconObj = NULL;
}
if (WorkbenchPort) {
struct Message *msg;
while ((msg = GetMsg(WorkbenchPort)) != NULL)
ReplyMsg(msg);
DeleteMsgPort(WorkbenchPort),
WorkbenchPort = NULL;
WorkbenchMask = 0;
}
if (WorkbenchBase) {
CloseLibrary(WorkbenchBase);
WorkbenchBase = NULL;
}
}
/*
* WriteIcon(filename)
*
* Writes a SnoopDos project icon to the associated filename. If an
* icon already exists for the filename, then that icon is left alone.
*
* If no icon exists, then we create one using a copy of what we think
* is the icon SnoopDos was started from (or the default).
*/
void WriteIcon(char *filename)
{
struct DiskObject newobj;
struct DiskObject *dobj;
if (!IconBase)
return;
dobj = GetDiskObject(filename);
if (dobj) {
FreeDiskObject(dobj);
return;
}
dobj = GetProgramIcon();
/*
* We can create a copy of our tool icon and change
* it to a project icon.
*/
newobj = *dobj;
newobj.do_CurrentX = NO_ICON_POSITION;
newobj.do_CurrentY = NO_ICON_POSITION;
newobj.do_ToolTypes = DefToolTypes;
newobj.do_Type = WBPROJECT;
if (WBenchMsg)
newobj.do_DefaultTool = WBenchMsg->sm_ArgList->wa_Name;
else
newobj.do_DefaultTool = GetCommandName();
PutDiskObject(filename, &newobj);
}
/*
* AddProgramToWorkbench(hidetype)
*
* Creates an AppIcon or AppMenuItem which can be used to re-active
* SnoopDos, and attaches it to Workbench. Normally used when
* SnoopDos goes into a HIDE state.
*
* Hidetype is HIDE_ICON or HIDE_TOOLS, depending on which type of
* hide method is required.
*
* Initialises WorkbenchMask accordingly.
*
* Call RemoveProgramFromWorkbench() to remove the item later on.
*
* Returns TRUE for success, FALSE for failure.
*/
int AddProgramToWorkbench(int hidetype)
{
if (!IconBase)
return (FALSE);
if (!WorkbenchBase) {
WorkbenchBase = OpenLibrary("workbench.library", 37);
if (!WorkbenchBase)
return (FALSE);
}
if (!WorkbenchPort) {
WorkbenchPort = CreateMsgPort();
if (!WorkbenchPort)
return (FALSE);
WorkbenchMask = (1 << WorkbenchPort->mp_SigBit);
}
if (hidetype == HIDE_TOOLS && !MyAppMenu) {
/*
* Adding an item to the Workbench tools menu
*/
MyAppMenu = AddAppMenuItem(0, 0, MSG(MSG_APPMENU_NAME),
WorkbenchPort, NULL);
if (!MyAppMenu)
return (FALSE);
}
if (hidetype == HIDE_ICON && !MyAppIcon) {
/*
* Adding an AppIcon to the Workbench. We make a copy
* of the current program icon to use as our appicon.
*/
struct DiskObject *dobj;
if (!AppIconObj) {
/*
* We need a temporary icon to play around with.
* We allocate a new default disk object, copy
* it, and modify our copy to give us an icon
* we can use as an AppIcon. We need to remember
* to free the original icon before we exit.
*/
static struct DiskObject defobj;
DefIconObj = GetDefDiskObject(WBTOOL);
if (!DefIconObj)
return (FALSE);
defobj = *DefIconObj;
AppIconObj = &defobj;
dobj = GetProgramIcon();
AppIconObj->do_Gadget.Width = dobj->do_Gadget.Width;
AppIconObj->do_Gadget.Height = dobj->do_Gadget.Height;
AppIconObj->do_Gadget.Flags = dobj->do_Gadget.Flags;
AppIconObj->do_Gadget.GadgetRender = dobj->do_Gadget.GadgetRender;
AppIconObj->do_Gadget.SelectRender = dobj->do_Gadget.SelectRender;
AppIconObj->do_Type = 0;
}
AppIconObj->do_CurrentX = CurSettings.IconPosLeft != -1 ?
CurSettings.IconPosLeft :
NO_ICON_POSITION;
AppIconObj->do_CurrentY = CurSettings.IconPosTop != -1 ?
CurSettings.IconPosTop :
NO_ICON_POSITION;
MyAppIcon = AddAppIcon(0, 0, APPICON_NAME, WorkbenchPort,
NULL, AppIconObj, TAG_DONE);
if (!MyAppIcon)
return (FALSE);
}
return (TRUE);
}
/*
* RemoveProgramFromWorkbench()
*
* Removes any AppIcon or AppMenuItem item that is currently installed
* on Workbench. Usually called when the SnoopDos window is about
* about to reappear.
*/
void RemoveProgramFromWorkbench(void)
{
if (MyAppMenu) RemoveAppMenuItem(MyAppMenu), MyAppMenu = NULL;
if (MyAppIcon) RemoveAppIcon(MyAppIcon), MyAppIcon = NULL;
}
/*
* HandleWorkbenchMsgs()
*
* Handles any outstanding messages at the Workbench message port
*/
void HandleWorkbenchMsgs(void)
{
struct AppMessage *msg;
int show = 0;
if (!WorkbenchPort)
return;
while ((msg = (void *)GetMsg(WorkbenchPort)) != NULL) {
show = 1;
ReplyMsg(msg);
}
if (show)
ShowSnoopDos();
}